import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class ECC_Client {
	static long P,A,B,Gx,Gy,N;
	public static void main(String[] args) throws IOException 
	  {
		 long random,Cx=0,Cy=0;
		 int count=1,len=0;
		 Scanner scan=new Scanner(System.in);
		 long[] result=new long[2],input=new long[2],SharedSec=new long[2];
		 System.out.println("Enter P");
		 P=scan.nextLong();
		 System.out.println("Enter a");
		 A=scan.nextLong();
		 System.out.println("Enter b");
		 B=scan.nextLong();
		 System.out.println("Enter Gx");
		 Gx=scan.nextLong();
		 System.out.println("Enter Gy");
		 Gy=scan.nextLong();
		 System.out.println("Enter N");
		 N=scan.nextLong();
		 System.out.println("Enter random number between 1 to "+(N-1));
		 random=scan.nextLong();
		 result[0]=Gx;
		 result[1]=Gy;
		 for(int i=1;i<random;i++)
		 {
			 result=Same_Points_Addition(result);
			 count++;
		 }
		 System.out.print("Public key is: ");
		 System.out.print("("+result[0]+",");
		 System.out.print(result[1]+")\n");
		 if(result[0]<0)
			 result[0]=-result[0];
		 if(result[1]<0)
			 result[1]=-result[1];
		 Socket soc = new Socket("localhost", 6009); 
		 System.out.println("Client is ready");
	     OutputStream outputStream = soc.getOutputStream(); 
	     PrintWriter printwriter = new PrintWriter(outputStream, true);                    
	     InputStream inputStream = soc.getInputStream();
	     //Receive Data
	     len=inputStream.read();
	     for(int i=0;i<len;i++)
	     {
	    	 input[i]=inputStream.read();
	     }
	     //Send Data
	     len=result.length;
	     outputStream.write(len);
	     for(int i=0;i<len;i++)
	     {
	    	outputStream.write((int) result[i]);
	     }
		 printwriter.flush(); 
		 //
		 Cx=input[0];
	     Cy=input[1];
	     System.out.println("Partial Key is: ("+Cx+","+Cy+")");  
	     SharedSec[0]=Cx;
	     SharedSec[1]=Cy;
	     for(int i=1;i<random;i++)
	     {
	    	 SharedSec=Same_Points_Addition(SharedSec);
	     }
	     if(SharedSec[0]<0)
	    	 SharedSec[0]=-SharedSec[0];
		 if(SharedSec[1]<0)
			 SharedSec[1]=-SharedSec[1];
	     System.out.println("Shared Secret is ("+SharedSec[0]+","+SharedSec[1]+")");
	  }
	static long[] Same_Points_Addition(long[] input)
	{
		long[] result=new long[2];
		double lambda=0;
		long x=input[0],y=input[1];
		if(y!=0)
		lambda=(((3*(x*x))+A)/(2*y));
		result[0]=(long) (((lambda*lambda)-x-x)%P);
		result[1]=(long) (((lambda*(x-result[0])-y))%P);
		return result;
	}
}
/*
*OUTPUT:
------------------------------------------
*Server:
Enter P
13
Enter a
2
Enter b
4
Enter Gx
3
Enter Gy
5
Enter N
23
Enter random number between 1 to 22
5
Public key is: (2,6)
Server is ready
Partial Key is: (9,10)
Shared Secret is (9,10)

------------------------------------------
Client:
Enter P
13
Enter a
2
Enter b
4
Enter Gx
3
Enter Gy
5
Enter N
23
Enter random number between 1 to 22
13
Public key is: (9,10)
Client is ready
Partial Key is: (2,6)
Shared Secret is (9,10)

 */
